/*
 * Matrix.cpp
 *
 *  Created on: 11.04.2012
 *      Author: delgado
 */

#include "Matrix.h"

using std::cout;
using std::endl;

namespace neurignacio{

Matrix::Matrix(const size_t& w, const size_t& h, const data_t& background) : width(w), height(h)
{
	array = new data_t* [height];
	for (register size_t y=0; y<height; ++y)
	{
		array[y] = new data_t [width];
		for (register size_t x=0; x<width; ++x)
		{
			array[y][x] = background;
		}
	}
}

Matrix::Matrix(const Matrix& matrix) : width(matrix.width), height(matrix.height)
{
	array = new data_t* [height];
	for (register size_t y=0; y<height; ++y)
	{
		array[y] = new data_t [width];
		for (register size_t x=0; x<width; ++x)
		{
			array[y][x] = matrix.array[y][x];
		}
	}
}

Matrix& Matrix::operator=(const Matrix& matrix)
{
	if (this!= &matrix)	// Protect against self-assignment
		if (width==matrix.width && height==matrix.height)	// Both matrices should have same shape
		{
			for (register size_t y=0; y<height; ++y)
				for (register size_t x=0; x<width; ++x)
					array[y][x] = matrix.array[y][x];
		}
	return *this;
}

Matrix::~Matrix()
{
	for (register size_t y=0; y<height; ++y)
		delete [] array[y];
	delete [] array;
}

Matrix Matrix::transpose(void)
{
	Matrix T(height, width);
	for (register size_t y=0; y<height; ++y)
		for (register size_t x=0; x<width; ++x)
			T(x,y)=(*this)(y,x);
	return T;
}

vector<Matrix::data_t> inner(const Matrix& A, const vector<Matrix::data_t>& b)
{
	vector<Matrix::data_t> X(A.height,0);
//	cout << "calculating inner product=> A(width=" << A.width << ", height=" << A.height << "), b.size()=" << b.size() << ", X.size()=" << X.size() << endl;
	if (A.height==b.size())
	{
	for (register size_t x=0; x<A.height; ++x)
		for (register size_t y=0; y<A.width; ++y)
		{

//			cout << "("<<x << ","<< y << ")="<< (int)A(x,y) << " x b(" << y << ")=" << (int)b[y] << " => " << (int)(A(x,y)*b[y]) << " + X("<<x <<")=" << (int)X[x];
			X[x] += A(x,y)*b[y];
//			cout << " Result: " << (int)X[x] << endl;
		}
	}
	return X;
}


ostream& operator<<(ostream& out, const Matrix& matrix)
{
	for (register size_t y=0; y<matrix.height; ++y)
	{
		for (register size_t x=0; x<matrix.width; ++x)
			out << (int)matrix(x,y) << " ";
		out << endl;
	}
	return out;
}

} // end namespace neurignacio
